#pragma once
#include <iostream>
#include <string>
#include "TcpServer.hpp" //如果这里包了，TcpServer就包不了了 //不会报错，文件名写错了
#include "InetAddr.hpp"
#include <functional>
#include <unistd.h>

class TcpServer; // 只能这么操作
class Connection;
using func_t = std::function<void(Connection *)>;

class Connection // 对链接的封装
{
public:
    Connection(int sockfd, uint32_t events, TcpServer *tsvr, InetAddr addr)
        : _sockfd(sockfd), _events(events), _R(tsvr), _addr(_addr)
    {
    }
    void RegisterCallback(func_t recver, func_t sender, func_t excepter)
    {
        _recver = recver;
        _sender = sender;
        _excepter = excepter;
    }
    int GetSockfd()
    {
        return _sockfd;
    }
    uint32_t GetEvents()
    {
        return _events;
    }
    std::string& BufferIn()
    {
        return _bufferin;
    }
    std::string& BufferOut()
    {
        return _bufferout;
    }
    ~Connection()
    {
        std::cout << "~Connection" << std::endl;
        close(_sockfd);
    }
    void SetEvents(uint32_t events)
    {
        _events = events;
    }
private:
    int _sockfd;
    uint32_t _events;
    std::string _bufferin;
    std::string _bufferout;
    InetAddr _addr; // 保存一下当前链接的ip和port
public:
    TcpServer *_R;
    func_t _recver;
    func_t _sender;
    func_t _excepter;
};

class ConnectionFactory
{
public: // 这里也可以选择用重载，或者listen多余的传空
    static Connection *CreateListenConnection(int sockfd, uint32_t events, func_t recver, TcpServer *tsvr, InetAddr addr)
    {
        Connection *conn = new Connection(sockfd, events, tsvr, addr);
        conn->RegisterCallback(recver, nullptr, nullptr);
        return conn;
    }
    static Connection *CreateNormalConnection(int sockfd,
                                              uint32_t events,
                                              TcpServer *tsvr,
                                              func_t recver,
                                              func_t sender,
                                              func_t excepter,
                                              InetAddr addr)
    {
        Connection *conn = new Connection(sockfd, events, tsvr, addr);
        conn->RegisterCallback(recver, sender, excepter);
        return conn;
    }
};